package com.fangque.kepp.framework.config.filter;

import com.fangque.kepp.framework.result.ResultBean;
import com.fangque.kepp.framework.user.entity.User;
import com.fangque.kepp.framework.user.entity.UserToken;
import com.fangque.kepp.framework.user.service.UserServiceImpl;
import com.fangque.kepp.framework.util.JwtTokenUtil;
import com.fangque.kepp.framework.util.ResponseUtil;
import com.fangque.kepp.framework.util.SpringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author: Lan
 * @date: 2019/4/8 15:27
 * @description:处理登录请求
 */
public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private UserServiceImpl userService;

    private AuthenticationManager authenticationManager;

    public JwtLoginFilter(AuthenticationManager authenticationManager) {
        super.setFilterProcessesUrl("/user/login");
        this.authenticationManager = authenticationManager;
    }

    /**
     * 请求登录
     *
     * @param request
     * @param response
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (!RequestMethod.POST.name().equals(request.getMethod())) {
            ResponseUtil.write(response, ResultBean.error("登录只能使用POST请求"));
            return null;
        }
        User user = new User();
        user.setUsername(request.getParameter("username"));
        user.setPassword(request.getParameter("password"));
        checkLoginForm(user, response);
        return authenticationManager
                .authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(),
                        user.getPassword(), user.getAuthorities()));
    }

    /**
     * 登录成功后
     *
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                            FilterChain chain, Authentication authResult)
            throws IOException, ServletException {
        User principal = (User) authResult.getPrincipal();
        if (jwtTokenUtil == null) {
            jwtTokenUtil = (JwtTokenUtil) SpringUtils.getBean("jwtTokenUtil");
        }
        UserToken userToken = new UserToken();
        userToken.setId(principal.getId());
        userToken.setUsername(principal.getUsername());
        userToken.setRoles(principal.getRoles());
        if (userService == null) {
            userService = SpringUtils.getBean(UserServiceImpl.class);
        }
        String token = jwtTokenUtil.createToken(userToken);
        //将token放置请求头返回
        response.addHeader(jwtTokenUtil.getTokenHeader(), jwtTokenUtil.getTokenPrefix() + token);
        ResponseUtil.write(response, ResultBean.success("登陆成功", jwtTokenUtil.getTokenPrefix() + token));
    }

    /**
     * 登录失败
     *
     * @param request
     * @param response
     * @param failed
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                              AuthenticationException failed) {
        String errorMessage = "";
        if (failed instanceof BadCredentialsException ||
                failed instanceof UsernameNotFoundException) {
            errorMessage = "账户名或者密码输入错误!";
        } else if (failed instanceof LockedException) {
            errorMessage = "账户被锁定，请联系管理员!";
        } else if (failed instanceof CredentialsExpiredException) {
            errorMessage = "密码过期，请联系管理员!";
        } else if (failed instanceof AccountExpiredException) {
            errorMessage = "账户过期，请联系管理员!";
        } else if (failed instanceof DisabledException) {
            errorMessage = "账户被禁用，请联系管理员!";
        } else {
            errorMessage = "登录失败!";
        }
        ResponseUtil.write(response, ResultBean.error(errorMessage));
    }

    /**
     * 校验参数
     *
     * @param user
     */
    private void checkLoginForm(User user, HttpServletResponse response) {
        if (StringUtils.isEmpty(user.getUsername())) {
            ResponseUtil.write(response, ResultBean.error("用户名不能为空"));
        } else if (StringUtils.isEmpty(user.getPassword())) {
            ResponseUtil.write(response, ResultBean.error("密码不能为空"));
        }
    }
}
